﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Net.Http;
//using System.Threading.Tasks;
//using Microsoft.Extensions.DependencyInjection;
//using Microsoft.Extensions.Logging;
//using Microsoft.Extensions.Options;
//using PasteCodeTaskBase;
//using PasteTimer.slavemodels;
//using Volo.Abp.DependencyInjection;
//using Z.EntityFramework.Plus;

//namespace PasteTimer
//{

//    /// <summary>
//    /// 
//    /// </summary>
//    public class SlaveHelper : ISingletonDependency
//    {
//        private SlaveMaster _master;

//        private SlaveMaster _myinfo;

//        private readonly ILogger<SlaveHelper> _logger;

//        private readonly IHttpClientFactory _httpClientFactory;

//        private readonly ChannelHelper _channelHelper;

//        private TaskNodeConfig _nodeconfig;

//        private readonly TaskConfig _config;

//        //private readonly IAppCache _cache;

//        private readonly IServiceProvider _serviceProvider;

//        /// <summary>
//        /// 寻找密钥，用于确定哪个地址是自己的
//        /// </summary>
//        private string _temptoken = String.Empty;

//        /// <summary>
//        /// 
//        /// </summary>
//        private List<SlaveInfoDto> _slavelist;

//        /// <summary>
//        /// 最后交互时间 时间戳秒
//        /// </summary>
//        private long lasttime = 0;


//        /// <summary>
//        /// 
//        /// </summary>
//        public SlaveHelper(
//            ILogger<SlaveHelper> logger,
//            IHttpClientFactory httpClientFactory,
//            IOptions<TaskNodeConfig> config,
//            IServiceProvider serviceProvider,
//            ChannelHelper chennel,
//            IOptions<TaskConfig> mconfig
//            )
//        {
//            _temptoken = Guid.NewGuid().ToString().Replace("-", "").ToLower();
//            _logger = logger;
//            _httpClientFactory = httpClientFactory;
//            _master = null;
//            _myinfo = null;
//            _channelHelper = chennel;
//            _nodeconfig = config.Value;
//            _config = mconfig.Value;
//            //_cache = cache;
//            _serviceProvider = serviceProvider;
//        }

//        /// <summary>
//        /// 我的节点ID
//        /// </summary>
//        public int MySlaveId { get { if (_myinfo == null) { return 0; } else { return _myinfo.id; } } }
//        /// <summary>
//        /// 我的节点密钥
//        /// </summary>
//        public string MySlaveToken { get { if (_myinfo == null) { return ""; } else { return _myinfo.token; } } }

//        /// <summary>
//        /// 获取管理者的信息
//        /// </summary>
//        public SlaveMaster Master { get { return _master; } }

//        /// <summary>
//        /// 获取自己的信息
//        /// </summary>
//        public SlaveMaster MyMaster { get { return _myinfo; } }

//        /// <summary>
//        /// 自己是否是管理员
//        /// </summary>
//        public bool IsMaster
//        {
//            get
//            {
//                if (_master != null)
//                {
//                    if (_myinfo != null)
//                    {
//                        if (_myinfo.id == _master.id)
//                        {
//                            return true;
//                        }
//                    }
//                }
//                return false;
//            }
//        }

//        /// <summary>
//        /// 是否确认了自己的节点
//        /// </summary>
//        public bool IsFind
//        {
//            get
//            {
//                if (_myinfo != null)
//                {
//                    if (_myinfo.id != 0)
//                    {
//                        return true;
//                    }
//                }
//                return false;
//            }
//        }

//        /// <summary>
//        /// 寻找密钥
//        /// </summary>
//        public String FindGuid { get { return _temptoken; } }

//        /// <summary>
//        /// 设置管理员
//        /// </summary>
//        /// <param name="input"></param>
//        public void SetMaster(SlaveMaster input)
//        {

//            _master = input;
//            if (input != null)
//            {
//                //有人成为master了 看看是否是自己
//                if (IsMaster)
//                {
//                    _channelHelper.WriteSlaveAction(new SlaveEventModel() { Event = "startmaster", Object = "" });
//                }
//                else
//                {
//                    _channelHelper.WriteSlaveAction(new SlaveEventModel() { Event = "stopmaster", Object = "" });
//                }
//            }
//            if (_master != null)
//            {
//                _nodeconfig.MasterUrl = _master.url;
//            }
//        }

//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="input"></param>
//        /// <returns></returns>
//        public async Task<SlaveCallBack> VoteCompare(SlaveMaster input)
//        {
//            if (_master == null)
//            {
//                //直接让对方当选
//                SetMaster(input);
//                return new SlaveCallBack();
//            }
//            else
//            {
//                //抛弃自己现有的，使用对方的
//                if (input.time < _master.time)
//                {
//                    SetMaster(input);
//                }
//                else
//                {
//                    //旧的是否可用
//                    var result = await Link(_master);
//                    if (result.code == 200)
//                    {
//                        //旧的还能用
//                        return new SlaveCallBack()
//                        {
//                            code = 213,
//                            message = Newtonsoft.Json.JsonConvert.SerializeObject(_master)
//                        };
//                    }
//                    else
//                    {
//                        //旧的不能用了
//                        SetMaster(input);
//                    }
//                }
//            }
//            return new SlaveCallBack();
//        }

//        /// <summary>
//        /// 链接到某一个节点
//        /// </summary>
//        /// <param name="to"></param>
//        /// <returns></returns>
//        public async Task<(int code, string message)> Link(SlaveMaster to)
//        {
//            if (to != null && _myinfo != null)
//            {
//                var time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                var temptoken = $"{time}_{_myinfo.id}_{to.id}_{_myinfo.token}_{to.token}".ToMd5Lower();
//                var xtoken = $"{time}_{_myinfo.id}_{to.id}_{temptoken}";
//                var result = await post($"{to.url}api/task/slave/link", "", xtoken);
//                return result;
//            }
//            else
//            {
//                return (500, "信息不全，无法进行操作！");
//            }
//        }

//        /// <summary>
//        /// 健康检查，往master检查
//        /// </summary>
//        /// <returns></returns>
//        public async Task<(int code, string message)> Health()
//        {
//            var nowminsec = DateTimeOffset.Now.AddSeconds(-60).ToUnixTimeMilliseconds();
//            if (nowminsec > lasttime)
//            {
//                if (_master != null && _myinfo != null)
//                {
//                    if (!IsMaster)
//                    {
//                        var time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                        var temptoken = $"{time}_{_myinfo.id}_{_master.id}_{_myinfo.token}_{_master.token}".ToMd5Lower();
//                        var xtoken = $"{time}_{_myinfo.id}_{_master.id}_{temptoken}";
//                        var postobj = new SlaveMaster()
//                        {
//                            id = _myinfo.id,
//                            time = _myinfo.time,
//                            url = _myinfo.url
//                        };
//                        var result = await post($"{_master.url}api/task/slave/health", Newtonsoft.Json.JsonConvert.SerializeObject(postobj), xtoken);
//                        if (result.code == 200)
//                        {
//                            lasttime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                            //如果master变更了，则接受新的
//                            var call = Newtonsoft.Json.JsonConvert.DeserializeObject<SlaveCallBack>(result.message);
//                            if (call != null && call != default)
//                            {
//                                if (call.code == 213)
//                                {
//                                    var master = Newtonsoft.Json.JsonConvert.DeserializeObject<SlaveMaster>(result.message);
//                                    if (master != null)
//                                    {
//                                        SetMaster(master);
//                                        //更换了新的master
//                                    }
//                                }
//                            }
//                        }
//                        return result;
//                    }
//                    else
//                    {
//                        return (200, "检查成功，自己为master,直接默认成功！");
//                    }
//                }
//                else
//                {
//                    return (500, "信息不全，无法进行操作！");
//                }
//            }
//            return (200, "时限内有交互，不需要心跳包");
//        }

//        /// <summary>
//        /// slave 中把事件信息发送给master
//        /// </summary>
//        /// <param name="input"></param>
//        /// <returns></returns>
//        public async Task<(int code, string message)> PostAction(SlaveEventModel input)
//        {
//            if (_master != null && _myinfo != null)
//            {
//                var time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                var temptoken = $"{time}_{_myinfo.id}_{_master.id}_{_myinfo.token}_{_master.token}".ToMd5Lower();
//                var xtoken = $"{time}_{_myinfo.id}_{_master.id}_{temptoken}";
//                var result = await post($"{_master.url}api/task/slave/action", Newtonsoft.Json.JsonConvert.SerializeObject(input), xtoken);
//                if (result.code == 200)
//                {
//                    lasttime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                }
//                return result;
//            }
//            else
//            {
//                return (500, "信息不全，无法进行操作！");
//            }
//        }

//        /// <summary>
//        /// 推送消息
//        /// </summary>
//        /// <param name="input"></param>
//        /// <returns></returns>
//        public async Task<(int code, string message)> PostNotify(noticemodels.NoticeLogAddDto input)
//        {
//            if (_master != null && _myinfo != null)
//            {
//                var time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                var temptoken = $"{time}_{_myinfo.id}_{_master.id}_{_myinfo.token}_{_master.token}".ToMd5Lower();
//                var xtoken = $"{time}_{_myinfo.id}_{_master.id}_{temptoken}";
//                var result = await post($"{_master.url}api/task/slave/notifiy", Newtonsoft.Json.JsonConvert.SerializeObject(input), xtoken);
//                if (result.code == 200)
//                {
//                    lasttime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                }
//                return result;
//            }
//            else
//            {
//                return (500, "信息不全，无法进行操作！");
//            }
//        }

//        /// <summary>
//        /// master提交离线通知给slave
//        /// </summary>
//        /// <returns></returns>
//        public async Task<(int code, string message)> PostOffline(SlaveMaster postto)
//        {
//            if (postto != null && _myinfo != null)
//            {
//                var time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                var temptoken = $"{time}_{_myinfo.id}_{postto.id}_{_myinfo.token}_{postto.token}".ToMd5Lower();
//                var xtoken = $"{time}_{_myinfo.id}_{postto.id}_{temptoken}";
//                var result = await post($"{postto.url}api/task/slave/offline", "", xtoken);
//                return result;
//            }
//            else
//            {
//                return (500, "信息不全，无法进行操作！");
//            }
//        }


//        /// <summary>
//        /// 
//        /// </summary>
//        /// <param name="url"></param>
//        /// <param name="body"></param>
//        /// <param name="xtoken"></param>
//        /// <returns></returns>
//        private async Task<(int code, string message)> post(string url, string body, string xtoken)
//        {
//            try
//            {
//                using HttpContent httpcontent = new StringContent(body);
//                var timestmp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                httpcontent.Headers.Add("xtoken", xtoken);
//                httpcontent.Headers.Add("stoken", _config.PublicToken);
//                httpcontent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json;charset=utf-8");
//                var client = _httpClientFactory.CreateClient();
//                client.Timeout = TimeSpan.FromSeconds(3);
//                using var response = await client.PostAsync(url, httpcontent);
//                var responseBody = await response.Content.ReadAsStringAsync();
//                if (response.IsSuccessStatusCode)
//                {
//                    return (200, responseBody);
//                }
//                else
//                {
//                    return (500, responseBody);
//                }
//            }
//            catch (Exception exl)
//            {
//                _logger.LogException(exl);
//                return (500, exl.Message);
//            }
//        }

//        /// <summary>
//        /// 启动竞选master，可能中途会被取消，要看谁先
//        /// </summary>
//        /// <returns></returns>
//        public async Task<int> StartVote(List<SlaveInfoDto> nodes)
//        {
//            _slavelist = nodes;
//            //如果这个过程中，有人来选举了... .. . 咋处理？
//            SetMaster(null);
//            var my = new SlaveMaster()
//            {
//                id = MySlaveId,
//                time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
//                token = _myinfo.token,
//                url = _myinfo.url
//            };
//            var boolbreak = false;
//            foreach (var item in nodes)
//            {
//                if (Master == null || Master.time > my.time)
//                {
//                    var time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                    var temptoken = $"{time}_{_myinfo.id}_{item.Id}_{_myinfo.token}_{item.Token}".ToMd5Lower();
//                    var xtoken = $"{time}_{_myinfo.id}_{item.Id}_{temptoken}";
//                    var result = await post($"{item.Url}api/task/slave/vote", Newtonsoft.Json.JsonConvert.SerializeObject(my), xtoken);
//                    Console.WriteLine($"{DateTime.Now} to vote url:{item.Url}");
//                    Console.WriteLine($"code:{result.code} message:{result.message}");

//                    if (result.code == 200)
//                    {
//                        var info = Newtonsoft.Json.JsonConvert.DeserializeObject<SlaveCallBack>(result.message);
//                        if (info != null && info != default)
//                        {
//                            if (info.code == 213)
//                            {
//                                var slove = Newtonsoft.Json.JsonConvert.DeserializeObject<SlaveMaster>(info.message);
//                                if (slove != null && slove != default)
//                                {
//                                    SetMaster(slove);
//                                }
//                                boolbreak = true;
//                                break;
//                            }
//                        }
//                    }
//                    else
//                    {
//                        //请求失败了
//                        _logger.LogError($"{DateTime.Now} foreach to vote master error! code:{result.code} message:{result.message} url:{item.Url}");
//                    }
//                }
//                else
//                {
//                    boolbreak = true;
//                    //有人捷足先登了
//                    break;
//                }
//            }
//            if (!boolbreak)
//            {
//                //自己成为master了
//                SetMaster(my);
//            }
//            return 1;
//        }

//        /// <summary>
//        /// 更新时间戳
//        /// </summary>
//        /// <param name="id"></param>
//        public bool SlaveUpdateTime(int id)
//        {
//            if (_slavelist != null)
//            {
//                var find = _slavelist.Where(x => x.Id == id).FirstOrDefault();
//                if (find != null && find != default)
//                {
//                    find.time = DateTimeOffset.Now.ToUnixTimeMilliseconds();
//                    return true;
//                }
//            }
//            return false;
//        }

//        /// <summary>
//        /// 把子节点加入到集合中
//        /// </summary>
//        /// <param name="input"></param>
//        public void SlaveAppend(SlaveMaster input)
//        {
//            var find = _slavelist.Where(x => x.Id == input.id).FirstOrDefault();
//            if (find == null || find == default)
//            {
//                _slavelist.Add(new SlaveInfoDto()
//                {
//                    Id = input.id,
//                    IsEnable = true,
//                    IsMaster = false,
//                    SlaveState = SlaveState.online,
//                    time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
//                    Token = input.token,
//                    Url = input.url
//                });
//            }
//        }

//        /// <summary>
//        /// 找到自己
//        /// </summary>
//        /// <param name="nodes"></param>
//        /// <returns></returns>
//        public async Task<int> FindMe(List<SlaveInfoDto> nodes)
//        {
//            foreach (var item in nodes)
//            {
//                var result = await post($"{item.Url}api/task/slave/find?guid=" + FindGuid, "", "");
//                if (result.code == 200)
//                {
//                    if (result.message == "200")
//                    {
//                        _myinfo = new SlaveMaster()
//                        {
//                            id = item.Id,
//                            time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
//                            token = item.Token,
//                            url = item.Url
//                        };
//                        _nodeconfig.Group = "slave";
//                        _nodeconfig.JoinToken = item.JoinToken;
//                        _nodeconfig.Url = item.Url;
//                        using var _scope = _serviceProvider.CreateScope();
//                        using var _dbContext = _scope.ServiceProvider.GetRequiredService<IPasteTimerDbContext>();
//                        await _dbContext.NodeInfo.Where(x => x.Id == item.Id).UpdateAsync(x => new taskmodels.NodeInfo() { Status = NodeStatus.running });
//                        break;
//                    }
//                }
//            }
//            return 1;
//        }


//        /// <summary>
//        /// 检查超时
//        /// </summary>
//        public void FindTimeOutList()
//        {
//            if (_slavelist != null && _slavelist.Count > 0)
//            {
//                var before = DateTimeOffset.Now.AddSeconds(-65).ToUnixTimeMilliseconds();
//                var timeoutlist = _slavelist.Where(x => x.time < before).ToList();
//                foreach (var item in timeoutlist)
//                {
//                    Console.WriteLine($"[health].timeout id:{item.Id} url:{item.Url}");
//                }
//            }
//        }
//    }
//}
